const cp = require('child_process');
const fs = require('fs');
var path = require('path');

var GCC = "C:\\Users\\zsh\\AppData\\Local\\Arduino15\\packages\\STMicroelectronics\\tools\\xpack-arm-none-eabi-gcc\\14.2.1-1.1/bin/arm-none-eabi-gcc";

var run = async (cmd, params) => {
  return new Promise((resolve, reject) => {
    var child;

    child = cp.spawn(cmd, params, {});

    var stdin = "";
    var stdout = "";
    var stderr = "";

    child.stdin.on('data', (data) => {
      stdin += data;
    });
    child.stdout.on('data', (data) => {
      stdout += data;
    });
    child.stderr.on('data', (data) => {
      stderr += data;
    });
    child.on('close', (code) => {
      if (true || code != 0) {
        console.log(`ret:${stdout} ${stderr} ${stdin}`);
        //setTimeout(() => { process.exit(1); }, 100);
      }
      resolve("");
    });
  });
};

/*
fatfs.c
ff.c
ffsystem.c
ffunicode.c
*/

var list = `by_spi.c
diskio_user.c
generic.c
hw_config.c
main.c
mass_mal.c
mass_storage.c
memory.c
misc.c
mmc.c
sdcard.c
scsi_data.c
stm32_it.c
stm32f10x_adc.c
stm32f10x_bkp.c
stm32f10x_can.c
stm32f10x_cec.c
stm32f10x_crc.c
stm32f10x_dac.c
stm32f10x_dbgmcu.c
stm32f10x_dma.c
stm32f10x_exti.c
stm32f10x_flash.c
stm32f10x_fsmc.c
stm32f10x_gpio.c
stm32f10x_i2c.c
stm32f10x_iwdg.c
stm32f10x_pwr.c
stm32f10x_rcc.c
stm32f10x_rtc.c
stm32f10x_sdio.c
stm32f10x_spi.c
stm32f10x_tim.c
stm32f10x_usart.c
stm32f10x_wwdg.c
system_stm32f10x.c
usb_bot.c
usb_core.c
usb_desc.c
usb_endp.c
usb_init.c
usb_int.c
usb_istr.c
usb_mem.c
usb_prop.c
usb_pwr.c
usb_regs.c
usb_scsi.c
usb_sil.c`;


//run(GPP, [...OPTCC.split(" "), ...INC3.split(" "), ...INC31.split(" "), INC2, "C:\\Users\\zsh\\AppData\\Local\\Arduino15\\packages\\STMicroelectronics\\hardware\\stm32\\2.11.0\\libraries\\SrcWrapper\\src\\HAL\\stm32yyxx_hal.c", "-o", ".\\build\\stm32yyxx_hal.c.o"]);

//GCC OPTCC INC3 INC2 "C:\\Users\\zsh\\AppData\\Local\\Arduino15\\packages\\STMicroelectronics\\hardware\\stm32\\2.11.0\\libraries\\SrcWrapper\\src\\HAL\\stm32yyxx_hal_dma.c" -o "C:\\Users\\zsh\\AppData\\Local\\Temp\\arduino_build_785406\\libraries\\SrcWrapper\\HAL\\stm32yyxx_hal_dma.c.o"
var opt1 = `-mcpu=cortex-m3 -DVECT_TAB_OFFSET=0x0 -DUSE_HAL_DRIVER -DUSE_FULL_LL_DRIVER -mthumb -c -Os -DNDEBUG -w -std=gnu17 -ffunction-sections -fdata-sections --param max-inline-insns-single=500 -MMD`;
var opt2 = `-DSTM32F1xx -DARDUINO=10812 -DARDUINO_BLACKPILL_F103C8 -DARDUINO_ARCH_STM32 -DBOARD_NAME="BLACKPILL_F103C8" -DVARIANT_H="variant_PILL_F103Cx.h" -DSTM32F103xB -DHAL_UART_MODULE_ENABLED`;

var proc = async () => {
  list = list.split("\n");
  var outfiles = [];
  for (let item of list) {
    var file = item.trim();
    await run(GCC, [...opt1.split(" "), ...opt2.split(" "), file, "-o", ".\\build\\" + file + ".o"]);
    outfiles.push(".\\build\\" + file + ".o");
  }

  var opt3 = `-mcpu=cortex-m3 -DVECT_TAB_OFFSET=0x0 -DUSE_HAL_DRIVER -DUSE_FULL_LL_DRIVER -mthumb -c -x assembler-with-cpp -DSTM32F1xx -DARDUINO=10812 -DARDUINO_BLACKPILL_F103C8 -DARDUINO_ARCH_STM32 -DBOARD_NAME="BLACKPILL_F103C8" -DVARIANT_H="variant_PILL_F103Cx.h" -DSTM32F103xB -DHAL_UART_MODULE_ENABLED`;
  
  await run(GCC, [...opt3.split(" "), "startup_stm32f103c8tx.s", "-o", ".\\build\\startup_stm32f103c8tx.s.o"]);

  // var opta = `-mcpu=cortex-m3 -mthumb -Os -DNDEBUG --specs=nano.specs -Wl,--defsym=LD_FLASH_OFFSET=0x0 -Wl,--defsym=LD_MAX_SIZE=65536 -Wl,--defsym=LD_MAX_DATA_SIZE=20480`;
  // var optb = `-Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common "-Wl,--default-script=./FLASH.ld" "-Wl,--script=./FLASH.ld"`;
  // var optc = `"-Wl,-Map,./build/sketch_oct30a.ino.map" -Wl,--no-warn-rwx-segments -o .\\build\\out.elf "-L.\\build" -Wl,--start-group`;
  // var optd = `-lc -Wl,--end-group -lm -lgcc -lstdc++`;

  var opta = `-mcpu=cortex-m3 -mthumb -Os -DNDEBUG --specs=nano.specs -Wl,--defsym=LD_FLASH_OFFSET=0x0 -Wl,--defsym=LD_MAX_SIZE=65536 -Wl,--defsym=LD_MAX_DATA_SIZE=20480`;
  var optb = `-Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--default-script=./FLASH.ld -Wl,--script=./FLASH.ld`;
  var optc = `-Wl,-Map,./build/out.map -Wl,--no-warn-rwx-segments -o .\\build\\out.elf -L.\\build -Wl,--start-group`;
  var optd = `-lc -Wl,--end-group -lm -lgcc -lstdc++`;

  await run(GCC, [...opta.split(" "), ...optb.split(" "), ...optc.split(" "), ...outfiles, ".\\build\\startup_stm32f103c8tx.s.o", ...optd.split(" ")]);

  var CPY = "C:\\Users\\zsh\\AppData\\Local\\Arduino15\\packages\\STMicroelectronics\\tools\\xpack-arm-none-eabi-gcc\\14.2.1-1.1/bin/arm-none-eabi-objcopy";

  await run(CPY, ["-O", "binary", ".\\build\\out.elf", ".\\build\\out.bin"]);

  await run(CPY, ["-O", "ihex", ".\\build\\out.elf", ".\\build\\out.hex"]);

};

proc();


const xx = ()=>{


//var root = "gcc base/";
var root = "gcc/";


var pause = () => {
  const readline = require('readline').createInterface({
    input: process.stdin,
    output: process.stdout,
  });

  readline.question(`pause`, name => {
    readline.close();
  });
};

var build = async (path, hardFloat, cpp, p) => {
  return new Promise((resolve, reject) => {
    var child;
    var param = ["-O2", "-Os", "-quiet", "-Wno-write-strings", "-Wno-attributes", "-Wno-builtin-declaration-mismatch", "-fno-builtin",
      "-G0",
      "-fno-unwind-tables",
      "-fno-asynchronous-unwind-tables",
      "-fno-pic",

      "-fno-exceptions",
      "-fno-trapv",
      "-fno-stack-protector",
      "-fno-delete-null-pointer-checks",
      "-fno-builtin-trap",
      "-fno-tree-dce",
      "-fno-tree-ccp"
    ];
    if (hardFloat) {
      param = [...param, "-mcustom-fadds=0", "-mcustom-fsubs=1", "-mcustom-fmuls=2", "-mcustom-fdivs=3", "-mcustom-fcmpeqs=8", "-mcustom-fcmpges=9", "-mcustom-fcmpgts=10", "-mcustom-fcmples=11", "-mcustom-fcmplts=12", "-mcustom-fcmpnes=13", "-mcustom-fixsi=14"];
    }
    param = [...param, ...p];

    var file = path.split("/");
    file = file[file.length - 1];
    var out = "build/" + file + ".s";
    param = [...param, path + (cpp ? ".cpp" : ".c"), "-o", out];

    if (cpp) {
      child = cp.spawn(root + "cc1plus.exe", param, {
        //cwd: job.path
      });
    } else {
      child = cp.spawn(root + "cc1.exe", param, {
        //cwd: job.path
      });
    }

    var stdin = "";
    var stdout = "";
    var stderr = "";

    child.stdin.on('data', (data) => {
      stdin += data;
    });
    child.stdout.on('data', (data) => {
      stdout += data;
    });
    child.stderr.on('data', (data) => {
      stderr += data;
    });
    child.on('close', (code) => {
      if (true || code != 0) {
        console.log(`${file} ${stdout} ${stderr} ${stdin}`);
        //setTimeout(() => { process.exit(1); }, 100);
      }
      resolve(out);
    });
  });
};

var read = async (filename) => {
  return new Promise((resolve, reject) => {
    fs.readFile(filename, function (err, content) {
      resolve(content);
    });
  });
};

var concat = async (files, target) => {
  var content = "";
  for (var i = 0; i < files.length; i++) {
    content += await read(files[i]);
  }

  fs.writeFileSync(target, content);
};
}

//module.exports = { build, pause, concat };

